/*	BehaviorTree definition.
 *
 *
*/

#include "BehaviorTree.h"

void BehaviorTree::Initialize()
{
	DEBUG_PRINT("=====================================================\n=====================================================\n");
	DEBUG_PRINT("Initializing Behavior Tree.\n");
	root = new Sequence("Root");	
	root = new ResetBehaviorDecorator(root,true);

	InitAttack();
	InitDefend();
	InitBuild();
	InitResearch();
	InitGather();
	InitScout();
	
	BaseBehavior* rallyAndPatrol = new RallyAndPatrol("RallyAndPatrol");
	((ParentBehaviorController*)root->GetControl())->Add(rallyAndPatrol);
	
	BB->Initialize();
	DebugPrintTree();
	root->GetControl()->SafeEnter();
}

void BehaviorTree::DebugPrintTree()
{
	DEBUG_PRINT("=========================================\n--Printing Behavior Tree-----------------\n=========================================\n");
	DebugPrintTreeTraversal(root,0,false,0);
	DEBUG_PRINT("=========================================\n--Printing Tree Done---------------------\n=========================================\n");
	
}

void BehaviorTree::DebugPrintTreeTraversal(BaseBehavior* current, int depth, bool last, unsigned int formatBitFlag)
{
	if(current)
	{
		for (unsigned int i = 0; i < 2*depth; i+=2)
		{
			debugTabs[i] =  (formatBitFlag & i) ? ' ' : '|';
			debugTabs[i+1] = '\t';
		}
		if(last)
		{
			debugTabs[2*depth] = '\\';
			debugTabs[2*depth+1] = '-';
			debugTabs[2*depth+2] = '-';
			debugTabs[2*depth+3] = '\0';
			formatBitFlag |= (depth)*2;
		}
		else
		{
			debugTabs[2*depth] = '+';
			debugTabs[2*depth+1] = '-';
			debugTabs[2*depth+2] = '-';
			debugTabs[2*depth+3] = '\0';
		}
		DEBUG_PRINT("%sBehavior(%p) %s at depth %d.  Started = %s ; Done = %s ; Success = %s.\n", debugTabs, current, current->GetName().c_str(), depth, BoolToString(current->GetControl()->Started()), BoolToString(current->GetControl()->Finished()), BoolToString(current->GetControl()->Succeeded()));
		if(current->GetControl()->GetSubBehaviors())
		{
			depth++;
			for(std::vector<BaseBehavior*>::iterator it = current->GetControl()->GetSubBehaviors()->begin(); it != current->GetControl()->GetSubBehaviors()->end(); it++)			
			{
				if(*it == current->GetControl()->GetSubBehaviors()->back())
					DebugPrintTreeTraversal((*it),depth,true, formatBitFlag);
				else
					DebugPrintTreeTraversal((*it),depth,false, formatBitFlag);
			}
		}
	}
	else
	{
		//Bottomed out on tree
	}
}

/*	Create Research branch.
 *
*/
void BehaviorTree::InitResearch()
{
	DEBUG_PRINT("Initializing Behavior Tree - Initializing Research branch.\n");
	BaseBehavior* research = new Sequence("Research");
	
	((ParentBehaviorController*)root->GetControl())->Add(research);

	ResearchStim* researchStim = new ResearchStim("ResearchStim");
	((ParentBehaviorController*)research->GetControl())->Add(researchStim);
	ResearchUpgrade* researchRange = new ResearchUpgrade(BWAPI::UpgradeTypes::U_238_Shells,"ResearchRange");
	((ParentBehaviorController*)research->GetControl())->Add(researchRange);
	ResearchUpgrade* researchInfantryArmor = new ResearchUpgrade(BWAPI::UpgradeTypes::Terran_Infantry_Armor,"ResearchInfantryArmor");
	((ParentBehaviorController*)research->GetControl())->Add(researchInfantryArmor);
	ResearchUpgrade* researchInfantryWeapons = new ResearchUpgrade(BWAPI::UpgradeTypes::Terran_Infantry_Weapons,"ResearchInfantryWeapons");
	((ParentBehaviorController*)research->GetControl())->Add(researchInfantryWeapons);
	ResearchTech* researchSpiderMines = new ResearchTech(BWAPI::TechTypes::Spider_Mines,"ResearchSpiderMines");
	((ParentBehaviorController*)research->GetControl())->Add(researchSpiderMines);
	ResearchTech* siegeMode = new ResearchTech(BWAPI::TechTypes::Tank_Siege_Mode,"ResearchSiegeMode");
	((ParentBehaviorController*)research->GetControl())->Add(siegeMode);
	ResearchUpgrade* researchIonThrusters = new ResearchUpgrade(BWAPI::UpgradeTypes::Ion_Thrusters,"ResearchIonThrusters");
	((ParentBehaviorController*)research->GetControl())->Add(researchIonThrusters);
	ResearchUpgrade* researchShipPlating = new ResearchUpgrade(BWAPI::UpgradeTypes::Terran_Ship_Plating,"ResearchShipPlating");
	((ParentBehaviorController*)research->GetControl())->Add(researchShipPlating);
	ResearchUpgrade* researchShipWeapons = new ResearchUpgrade(BWAPI::UpgradeTypes::Terran_Ship_Weapons,"ResearchShipWeapons");
	((ParentBehaviorController*)research->GetControl())->Add(researchShipWeapons);
	ResearchUpgrade* researchVehiclePlating = new ResearchUpgrade(BWAPI::UpgradeTypes::Terran_Vehicle_Plating,"ResearchShipPlating");
	((ParentBehaviorController*)research->GetControl())->Add(researchVehiclePlating);
	ResearchUpgrade* researchVehicleWeapons = new ResearchUpgrade(BWAPI::UpgradeTypes::Terran_Vehicle_Weapons,"ResearchShipWeapons");
	((ParentBehaviorController*)research->GetControl())->Add(researchVehicleWeapons);
}

/*	Create Attack branch.
 *
*/
void BehaviorTree::InitAttack()
{
	DEBUG_PRINT("Initializing Behavior Tree - Initializing Attack branch.\n");
	BaseBehavior* attack = new Sequence("Attack");

	
	((ParentBehaviorController*)root->GetControl())->Add(attack);
	InitAttackGroundUnits(attack);
	InitAttackAirUnits(attack);
}

/*	Create Attack Ground Units branch.
 *
*/
void BehaviorTree::InitAttackGroundUnits(BaseBehavior* attack)
{
	DEBUG_PRINT("Initializing Behavior Tree - Initializing Attack Ground Units branch.\n");
	BaseBehavior* attackGround = new Sequence("AttackGround");
	attackGround = new GroundAttackSequenceDecorator(attackGround);
	
	((ParentBehaviorController*)attack->GetControl())->Add(attackGround);

	BaseBehavior* marineAttack = new GroundAttack();//new Behavior("MarineAttack");
	((ParentBehaviorController*)attackGround->GetControl())->Add(marineAttack);
	BaseBehavior* mechAttack = new MechAttack();//new Behavior("MarineAttack");
	((ParentBehaviorController*)attackGround->GetControl())->Add(mechAttack);
	
}

/*	Create Attacking Air Units branch.
 *
*/
void BehaviorTree::InitAttackAirUnits(BaseBehavior* attack)
{
	DEBUG_PRINT("Initializing Behavior Tree - Initializing Attack Air branch.\n");
	BaseBehavior* attackAir = new Sequence("AttackAir");
	
	((ParentBehaviorController*)attack->GetControl())->Add(attackAir);

	BaseBehavior* airAttack = new AirAttack("AirAttack");
	((ParentBehaviorController*)attackAir->GetControl())->Add(airAttack);
}

/*	Create Defend branch.
 *
*/
void BehaviorTree::InitDefend()
{
	DEBUG_PRINT("Initializing Behavior Tree - Initializing Defend branch.\n");
	BaseBehavior* defend = new Sequence("Defend");
	
	((ParentBehaviorController*)root->GetControl())->Add(defend);
	((ParentBehaviorController*)defend->GetControl())->Add(new BaseDefense());
	//InitDefendGroundUnits(defend);
	//InitDefendAirUnits(defend);
}

/*	Create Attack Ground Units branch.
 *
*/
void BehaviorTree::InitDefendGroundUnits(BaseBehavior* defend)
{
	DEBUG_PRINT("Initializing Behavior Tree - Initializing Defense for Ground Units branch.\n");
	BaseBehavior* defendGround = new Sequence("DefendGround");

	
	((ParentBehaviorController*)defend->GetControl())->Add(defendGround);

	BaseBehavior* defendGroundUnit = new BaseDefense("DefendGroundUnit");

	((ParentBehaviorController*)defendGround->GetControl())->Add(defendGroundUnit);
}

/*	Create Attacking Air Units branch.
 *
*/
void BehaviorTree::InitDefendAirUnits(BaseBehavior* defend)
{
	DEBUG_PRINT("Initializing Behavior Tree - Initializing Defense for branch.\n");
	BaseBehavior* defendAir = new Decider("DefendAir");

	
	((ParentBehaviorController*)defend->GetControl())->Add(defendAir);

	BaseBehavior* defendAirUnit = new Behavior("DefendAirUnit");

	((ParentBehaviorController*)defendAir->GetControl())->Add(defendAirUnit);
}


/*	Create Build branch.
*
*/
void BehaviorTree::InitBuild()
{
	DEBUG_PRINT("Initializing Behavior Tree - Initializing Build branch.\n");
	BaseBehavior* build = new Sequence("Build");

	
	((ParentBehaviorController*)root->GetControl())->Add(build);

	InitBuildUnits(build);
	InitBuildBuildings(build);
}
void BehaviorTree::InitBuildInfantry(BaseBehavior* build)
{
	BaseBehavior* buildInfantry = new Sequence("BuildInfantry");
	buildInfantry = new BuildInfantrySequenceDecorator(buildInfantry);
	((ParentBehaviorController*)build->GetControl())->Add(buildInfantry);
	
	BuildMedic* buildMedic = new BuildMedic("BuildMedic");
	BuildFirebat* buildFirebat = new BuildFirebat();
	BuildMarine* buildMarine = new BuildMarine("BuildMarine");
	
	((ParentBehaviorController*)buildInfantry->GetControl())->Add(buildMedic);
	((ParentBehaviorController*)buildInfantry->GetControl())->Add(buildFirebat);
	((ParentBehaviorController*)buildInfantry->GetControl())->Add(buildMarine);
}

void BehaviorTree::InitBuildMech(BaseBehavior* build)
{
	BaseBehavior* buildMech = new Sequence("BuildMech");
	((ParentBehaviorController*)build->GetControl())->Add(buildMech);

	BuildVulture* buildVulture = new BuildVulture("BuildVulture");
	((ParentBehaviorController*)buildMech->GetControl())->Add(buildVulture);
	BuildSiegeTank* buildTank = new BuildSiegeTank("BuildSiegeTank");
	((ParentBehaviorController*)buildMech->GetControl())->Add(buildTank);
	BuildGoliath* buildGoliath = new BuildGoliath("BuildGoliath");
	((ParentBehaviorController*)buildMech->GetControl())->Add(buildGoliath);
}

void BehaviorTree::InitBuildAir(BaseBehavior* build)
{
	BaseBehavior* buildAir = new Sequence("BuildAir");
	((ParentBehaviorController*)build->GetControl())->Add(buildAir );

	BuildScienceVessel* buildScienceVessel = new BuildScienceVessel("BuildScienceVessel");
	((ParentBehaviorController*)buildAir->GetControl())->Add(buildScienceVessel);
	BuildWraith* buildWraith = new BuildWraith("BuildWraith");
	((ParentBehaviorController*)buildAir->GetControl())->Add(buildWraith);
	BuildValkyrie* buildValkyrie = new BuildValkyrie("BuildValkyrie");
	((ParentBehaviorController*)buildAir->GetControl())->Add(buildValkyrie);
}

void BehaviorTree::InitBuildUnits(BaseBehavior* build)
{
	DEBUG_PRINT("Initializing Behavior Tree - Initializing Build Units branch.\n");
	
	BaseBehavior* buildUnits = new Sequence("BuildUnits");
	buildUnits = new BuildUnitsSequenceDecorator(buildUnits);

	((ParentBehaviorController*)build->GetControl())->Add(buildUnits);
	
	InitBuildInfantry(buildUnits);
	InitBuildMech(buildUnits);
	InitBuildAir(buildUnits);
	
	BuildSCV* buildSCV = new BuildSCV("BuildSCV");	
	((ParentBehaviorController*)buildUnits->GetControl())->Add(buildSCV);
}

void BehaviorTree::InitBuildBuildings(BaseBehavior* build)
{
	DEBUG_PRINT("Initializing Behavior Tree - Initializing Build Buildings branch.\n");
	BaseBehavior* buildBuildings = new Sequence("BuildBuildings");

	((ParentBehaviorController*)build->GetControl())->Add(buildBuildings);

	InitBuildProductionBuildings(buildBuildings);
	InitBuildResearchBuildings(buildBuildings);

	BaseBehavior* buildComsat = new BuildComsat("BuildComsat");
	((ParentBehaviorController*)buildBuildings->GetControl())->Add(buildComsat);
	BaseBehavior* buildCC = new BuildCommandCenter("BuildCommandCenter");
	((ParentBehaviorController*)buildBuildings->GetControl())->Add(buildCC);
	BaseBehavior* buildDepot = new BuildDepot("BuildDepot");
	((ParentBehaviorController*)buildBuildings->GetControl())->Add(buildDepot);
	BaseBehavior* buildRefinery = new BuildRefinery("BuildRefinery");
	((ParentBehaviorController*)buildBuildings->GetControl())->Add(buildRefinery);
}

void BehaviorTree::InitBuildProductionBuildings(BaseBehavior* build)
{
	BaseBehavior* buildBuildings = new Sequence("BuildProductionBuildings");
	buildBuildings = new ProductionBuildingSequenceDecorator(buildBuildings);
	((ParentBehaviorController*)build->GetControl())->Add(buildBuildings);

	BaseBehavior* buildFactory = new BuildFactory("BuildFactory");
	((ParentBehaviorController*)buildBuildings->GetControl())->Add(buildFactory);
	BaseBehavior* buildBarracks = new BuildBarracks("BuildBarracks");
	((ParentBehaviorController*)buildBuildings->GetControl())->Add(buildBarracks);
	BaseBehavior* buildStarport = new BuildStarport("BuildStarport");
	((ParentBehaviorController*)buildBuildings->GetControl())->Add(buildStarport);
}

void BehaviorTree::InitBuildResearchBuildings(BaseBehavior* build)
{
	BaseBehavior* buildBuildings = new Sequence("BuildBuildings");
	buildBuildings = new ResearchBuildingSequenceDecorator(buildBuildings);
	((ParentBehaviorController*)build->GetControl())->Add(buildBuildings);

	BaseBehavior* buildMachineShop = new BuildMachineShop("BuildMachineShop");
	((ParentBehaviorController*)buildBuildings->GetControl())->Add(buildMachineShop);
	BaseBehavior* buildControlTower = new BuildControlTower("BuildControlTower");
	((ParentBehaviorController*)buildBuildings->GetControl())->Add(buildControlTower);
	BaseBehavior* buildPhysicsLab = new BuildPhysicsLab("buildPhysicsLab");
	((ParentBehaviorController*)buildBuildings->GetControl())->Add(buildPhysicsLab);

	BaseBehavior* buildArmory = new BuildArmory("BuildArmory");
	((ParentBehaviorController*)buildBuildings->GetControl())->Add(buildArmory);
	BaseBehavior* buildAcademy = new BuildAcademy("BuildAcademy");
	((ParentBehaviorController*)buildBuildings->GetControl())->Add(buildAcademy);
	BaseBehavior* buildEngineeringBay = new BuildEngineeringBay("BuildEngineeringBay");
	((ParentBehaviorController*)buildBuildings->GetControl())->Add(buildEngineeringBay);	
	BaseBehavior* buildScienceFacility = new BuildScienceFacility("BuildScienceFacility");
	((ParentBehaviorController*)buildBuildings->GetControl())->Add(buildScienceFacility);
}


/*	Create Gather branch.
 *
*/
void BehaviorTree::InitGather()
{
	DEBUG_PRINT("Initializing Behavior Tree - Initializing Gather branch.\n");
	BaseBehavior* gather = new Sequence("GatherSequence");

	((ParentBehaviorController*)root->GetControl())->Add(gather);
	
	//ToDo: Add the gas
	BaseBehavior* gatherMin = new Gather("Gather");
	BaseBehavior* gatherGas = new GatherGas("GatherGas");
	((ParentBehaviorController*)gather->GetControl())->Add(gatherMin);
	((ParentBehaviorController*)gather->GetControl())->Add(gatherGas);
}

/*	Create Scout leaf node.
 *
*/
void BehaviorTree::InitScout()
{
	DEBUG_PRINT("Initializing Behavior Tree - Initializing Scout behavior.\n");
	BaseBehavior* scout = new Sequence("ScoutSequence");
	//scout = new ResetBehaviorDecorator(scout);

	((ParentBehaviorController*)root->GetControl())->Add(scout);
	
	// Later add other ways of scouting...? perhaps scans?
	BaseBehavior* genericScout = new Scout("Scout");
	((ParentBehaviorController*)scout->GetControl())->Add(genericScout);

	// vulture harass behavior
	BaseBehavior* vultureHarass = new VultureHarass("VultureHarass");
	((ParentBehaviorController*)scout->GetControl())->Add(vultureHarass);

	BaseBehavior* useComsat = new UseComsat("UseComsat");
	((ParentBehaviorController*)scout->GetControl())->Add(useComsat);
}

void BehaviorTree::Update()
{
	DEBUG_PRINT("=========================================\n--Updating Behavior Tree-----------------\n=========================================\n");
	BB->UpdateGameState();
	root->Execute();
}

void BehaviorTree::Finalize()
{
	DEBUG_PRINT("Finalizing Behavior Tree.\n");


}

BehaviorTree::~BehaviorTree()
{


}